#include <iostream>

// 函数模板生成的函数选择, 编译器将会使用哪个函数版本
// 所以对于函数重载,函数模版和函数模板重载,C++需要有一个良好的策略,来决定函数调用使用哪一个函数定义,尤其是存在多个参数的时候,这个过程叫做函数解析
// 虽然这些函数是通过编译器函数生成的,但是不是随意进行调用的,基本上是按照"最适配的函数"进行选择
// 下面,我将会围绕"最适配的函数"进行阐述

// 先声明几个函数和函数模板
void maybe(int);
float maybe(float, float = 3);
char *maybe(char);
char maybe(const char *);
template <class T> void maybe(const T &);
template <class T> void maybe(T *);
// 这样就会产生多个重载

int main()
{
    // 那么编译器将会使用哪个函数版本呢?
    // 大致的过程如下:
    // 1. 创建候选者列表. 其中包含与被调用函数的名称相同的函数和模板函数
    // 2. 使用候选者函数列表创建可行函数列表,这些都是参数个数正确的函数,为此有一个隐式转换序列,序列中会包含实参和形参类型完全匹配的情况.
        // 例如: float可以隐式的转换为double,从而与double类型列表函数匹配,而模板也可以为float生成一个实例
    // 3. 确定是否会有最佳的可行函数,如果有,则是用他,否则调用函数出错.

    // 假设存在下面的调用
    maybe('b');
    // 1.首先编译器将会寻找候选者,即为名称为maybe的函数和函数模版,然后寻找那些可以使用一个参数调用的函数(注意C++只考虑特征标识(也就是参数列表))
    // 上面声明的所有函数和函数模版都满足 名字 + 1个参数 这样的条件

    // 2.然后编译器将会为候选函数与函数原型匹配进行所需要的转换,通常按照下面的顺序:
        // 1.完全匹配 
        // 2.提升转换   char->int    float->double
        // 3.标准转换   int->char    long->double
        // 4.用户定义的转换     类声明中定义的转换

    // 3.寻找最匹配(准确的说是最少执行转换)的函数并且执行它

    // 总之就是按照: 非模板函数 -> 最合适的模板函数 -> 报错  的方式执行
    return 0;
}